package com.xdoc.client;

import com.xdoc.client.util.IOUtils;
import com.xdoc.client.util.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

/**
 * 接口调用类
 * @author coffish
 */
public class ApiInvoker {
    private final static Log logger = LogFactory.getLog(ApiInvoker.class);

    public static void invoke(String url, Map<String, Object> param, OutputStream out) throws IOException {
        HttpURLConnection httpConn = openHttp(url, param);
        String contentType = httpConn.getContentType();
        if (contentType.indexOf("json") >= 0) {
            //发生错误
            parse(httpConn.getInputStream());
        } else {
            IOUtils.pipe(httpConn.getInputStream(), out);
        }
    }
    public static Object invoke(String url, Map<String, Object> param) throws IOException {
        HttpURLConnection httpConn = openHttp(url, param);
        String contentType = httpConn.getContentType();
        if (contentType.indexOf("json") >= 0) {
            return parse(httpConn.getInputStream());
        } else {
            throw new IOException("无效contentType：" + contentType);
        }
    }
    private static HttpURLConnection openHttp(String url, Map<String, Object> param) throws IOException {
        logger.debug("调用服务接口：" + url);
        HttpURLConnection httpConn = (HttpURLConnection) new URL(url).openConnection();
        httpConn.setDoOutput(true);
        OutputStream reqOut = httpConn.getOutputStream();
        Iterator<String> it = param.keySet().iterator();
        String key, val;
        while (it.hasNext()) {
            key = it.next();
            reqOut.write('&');
            reqOut.write(IOUtils.urlEncode(key).getBytes());
            reqOut.write('=');
            val = toParamString(param.get(key));
            reqOut.write(IOUtils.urlEncode(val).getBytes());
            logger.debug("参数：" + key + "=" + val);
        }
        reqOut.flush();
        reqOut.close();
        httpConn.connect();
        return httpConn;
    }
    private static Object parse(InputStream in) throws IOException {
        String str = IOUtils.toString(in);
        Object obj = JSON.parse(str);
        if (obj instanceof Map) {
            Map resMap = (Map) obj;
            if (resMap.containsKey("success") && resMap.containsKey("result")) {
                if ("true".equals(String.valueOf(resMap.get("success")))) {
                    return resMap.get("result");
                } else {
                    throw new IOException(String.valueOf(resMap.get("result")));
                }
            }
        }
        throw new IOException("结果格式错误：" + str);
    }
    private static String toParamString(Object obj) throws IOException {
        String str;
        if (obj == null) {
            str = "";
        } else if (obj instanceof Boolean
                || obj instanceof Number
                || obj instanceof CharSequence) {
            str = obj.toString();
        } else if (obj instanceof Date) {
            str = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) obj);
        } else if (obj instanceof File) {
            str = IOUtils.toDataURI(((File) obj).getAbsolutePath());
        } else if (obj instanceof URL) {
            str = IOUtils.toDataURI((URL) obj);
        } else if (obj instanceof InputStream) {
            str = IOUtils.toDataURI((InputStream) obj);
        } else {
            str = JSON.stringify(obj);
        }
        return str;
    }
}
